<?php

namespace JsonLowCode;

use Closure;
use JsonLowCode\Support\Fluent;
use JsonLowCode\Traits\HasMake;

/**
// * @property string $name 路由名称
// * @property string $path 路由路径
// * @property string $component 路由组件
// * @property array $meta 路由元信息
// * @property array $children 子菜单
 */
class Menu extends Fluent
{
    private array $layouts = [
        "base"=>"layout.base",
        "blank"=>"layout.blank",
    ];
    protected string $layout = "layout.base";

    protected bool $isBlank = false;

    protected int $type = 0;
    protected string $prefix = "";

    /**
     * @param string $name
     * @param string|null $title
     * @param bool $isBlank
     * @param int $type 0:布局组件与页面组件混合, 1=布局组件, 2=页面组件
     */
    public function __construct(string $name,string $title = null, bool $isBlank = false, int $type = 1)
    {
        $this->isBlank = $isBlank;
        $this->name($name);
        if (str_contains($name,"_")){
            $this->path("/".str_replace("_","/",$name));
        }else{
            $this->path("/".$name);
        }
        $this->title($title?:$name);
        $this->initType($type);
    }

    /**
     * @param string $name
     * @param string|null $title
     * @return static
     */
    public static function base(string $name,string $title = null): static
    {
        return new self($name,$title,false, 1);
    }

    /**
     * @param string $name
     * @param string|null $title
     * @return static
     */
    public static function blank(string $name,string $title = null): static
    {
        return new self($name,$title, true, 1);
    }


    /**
     * @param string $name
     * @param string|null $title
     * @param bool $isBlank
     * @return static
     */
    public static function layout(string $name, string $title = null, bool $isBlank = false): static
    {
        return new self($name,$title,$isBlank, 0);
    }

    /**
     * @param string $name
     * @param string|null $title
     * @param bool $isBlank
     * @param int $type 0:布局组件与页面组件混合, 1=布局组件, 2=页面组件
     * @return static
     */
    public static function render(string $name, string $title = null, bool $isBlank = false, int $type = 0): static
    {
        return (new self($name,$title, $isBlank, $type))->component("render");
    }

    /**
     * @param string $name
     * @param string|null $title
     * @return static
     */
    public static function view(string $name,string $title = null): static
    {
        return new self($name,$title,false,2);
    }

    /**
     * @param string $name
     * @param string|null $title
     * @return static
     */
    public static function menu(string $name,string $title = null): static
    {
        return new self($name,$title,false,3);
    }

    /**
     * @param string $name
     * @param string|null $title
     * @return static
     */
    public static function iframe(string $name,string $title = null): static
    {
        return new self($name,$title,false,4);
    }

    /**
     * @param int $type 0:布局组件与页面组件混合, 1=布局组件, 2=页面组件, 3=目录
     * @return $this
     */
    private function initType(int $type = 0): static
    {
        $this->type = $type;
        switch ($type){
            case 1:
                $this->layout = $this->layouts[$this->isBlank?"blank":"base"];
                $this->component($this->layout);
                break;
            case 2:
                $this->prefix = "view";
                $this->component($this->name);
                break;
            case 3:
                break;
            case 4:
                $this->prefix = "view";
                $this->component("iframe-page");
                break;
            default:
                $this->layout = $this->layouts[$this->isBlank?"blank":"base"];
                $this->prefix = "\$view";
                $this->component($this->name);
                break;
        }
        return $this;
    }


    /**
     * 设置菜单标题
     * @param string $title
     * @return $this
     */
    public function title(string $title): static
    {
        return $this->meta("title",$title);
    }


    /**
     * 设置路由名称
     * @param string $name
     * @return $this
     */
    public function name(string $name): static
    {
         $this->name = $name;
         return $this;
    }

    /**
     * 设置路由路径
     * @param string $path
     * @return $this
     */
    public function path(string $path): static
    {
        $this->path = $path;
        return $this;
    }

    /**
     * 设置路由组件
     * @param string $component
     * @return $this
     */
    public function component(string $component): static
    {
        $prefix = $this->prefix;
        if ($prefix == "\$view"){
            $prefix = $this->layout.$this->prefix;
            $this->component = $prefix.".".$component;
        }else if($prefix == 'view'){
            $this->component = $prefix.".".$component;
        }else{
            $this->component = $component;
        }
        return $this;
    }

    /**
     * @param string $redirect
     * @return $this
     */
    public function redirect(string $redirect): static
    {
        $this->redirect = $redirect;
        return $this;
    }

    /**
     * 设置路由排序
     * @param int $order
     * @return $this
     */
    public function order(int $order): static
    {
        return $this->meta("order",$order);
    }

    /**
     * Iconify 图标
     * 可用于菜单或面包屑中
     * @param string $icon
     * @return $this
     */
    public function icon(string $icon): static
    {
        return $this->meta("icon",$icon);
    }

    /**
     * 本地图标
     * 存在于 "src/assets/svg-icon" 目录下，如果设置，将忽略icon属性
     * @param string $icon
     * @return $this
     */
    public function localIcon(string $icon): static
    {
        return $this->meta("localIcon",$icon);
    }

    /**
     * 路由的外部链接
     * @param string $href
     * @return $this
     */
    public function href(string $href): static
    {
        return $this->meta("href",$href);
    }

    /**
     * 是否缓存该路由
     * @param bool $keepAlive
     * @return $this
     */
    public function keepAlive(bool $keepAlive = true): static
    {
        return $this->meta("keepAlive",$keepAlive);
    }

    /**
     * 是否为常量路由, 无需登录，并且该路由在前端定义
     * @param bool $constant
     * @return $this
     */
    public function constant(bool $constant = true): static
    {
        return $this->meta("constant",$constant);
    }

    /**
     * 是否在菜单中隐藏该路由
     * @param bool $hideInMenu
     * @return $this
     */
    public function hideInMenu(bool $hideInMenu = true): static
    {
        return $this->meta("hideInMenu",$hideInMenu);
    }

    /**
     * 路由的国际化键值
     * 如果设置，将用于i18n，此时title将被忽略
     * @param string $i18nKey
     * @return $this
     */
    public function i18nKey(string $i18nKey): static
    {
        return $this->meta("i18nKey",$i18nKey);
    }

    /**
     * 路由的角色列表
     * 当前用户拥有至少一个角色时，允许访问该路由，角色列表为空时，表示无需权限
     * @param array<string> $roles
     * @return $this
     */
    public function roles(array $roles): static
    {
        return $this->meta("roles",$roles);
    }

    /**
     * 进入该路由时激活的菜单键, 该路由不在菜单中
     * @example 假设路由是"user_detail"，如果设置为"user_list"，则会激活"用户列表"菜单项
     * @param string $activeMenu
     * @return $this
     */
    public function activeMenu(string $activeMenu): static
    {
        return $this->meta("activeMenu",$activeMenu);
    }

    /**
     * 默认情况下，相同路径的路由会共享一个标签页，若设置为true，则使用多个标签页
     * @param bool $multiTab
     * @return $this
     */
    public function multiTab(bool $multiTab = true): static
    {
        return $this->meta("multiTab",$multiTab);
    }

    /**
     * @param bool|array $props
     * @return $this
     */
    public function props(bool|array $props = true): static
    {
        $this->attributes['props'] = $props;
        return $this;
    }

    /**
     * @param string $url
     * @return $this
     */
    public function url(string $url): static
    {
        return $this->props(['url'=>$url]);
    }

    /**
     * 若设置，路由将在标签页中固定显示，其值表示固定标签页的顺序
     * @param int $fixedIndexInTab
     * @return $this
     */
    public function fixedIndexInTab(int $fixedIndexInTab): static
    {
        return $this->meta("fixedIndexInTab",$fixedIndexInTab);
    }

    /**
     * 路由查询参数，如果设置的话，点击菜单进入该路由时会自动携带的query参数
     * @param array $query
     * @return $this
     */
    public function query(array $query): static
    {
        return $this->meta("query",$query);
    }


    /**
     * @param $key
     * @param $value
     * @return $this
     */
    public function meta($key,$value): static
    {
        $meta = $this->attributes['meta']??[];
        $meta[$key] = $value;
        $this->meta  = $meta;
        return $this;
    }


    /**
     * @param array<Menu>|Menu|Closure $children
     * @return $this
     */
    public function children(array|Menu|Closure $children = null): static
    {
        if($children){
            if ($children instanceof Closure){
                $children($this);
            }elseif ($children instanceof Menu){
                $this->children = array_merge($this->attributes['children']??[],[$children]);
            }else{
                $this->children = $children;
            }
        }
        return $this;
    }

    private function __clone() {}
}